﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using System.Collections;

namespace WenSkin.Controls
{
    public partial class WenDataGridView : DataGridView
    {
        public event DataGridViewCellMouseEventHandler TextBoxButtonClick;
        public WenDataGridView()
        {
            InitializeComponent();
            base.SetStyle(
                ControlStyles.UserPaint |
                ControlStyles.DoubleBuffer |
                ControlStyles.OptimizedDoubleBuffer |
                ControlStyles.AllPaintingInWmPaint |
                ControlStyles.ResizeRedraw |
                ControlStyles.SupportsTransparentBackColor, true);
            base.UpdateStyles();
            this.BackgroundColor = Color.White;
            this.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
        }

        public virtual void OnTextBoxButtonClick(DataGridViewCellMouseEventArgs e)
        {
            try
            {
                TextBoxButtonClick(this, e);
            }
            catch { }
        }

        #region 私有属性

        private StringFormat StringConters { get; set; }
            = new StringFormat(StringFormatFlags.NoClip | StringFormatFlags.NoWrap)
            {
                LineAlignment = StringAlignment.Center,
                Trimming = StringTrimming.EllipsisCharacter
            };        
        #endregion

        #region 公有属性
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [Category("Wen")]
        [Description("绑定数据节点信息设置")]
        public TreeDataSourceNode TreeDataSourceNode { get; set; } = new TreeDataSourceNode();

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [Category("Wen")]
        [Description("折叠按钮缩进值")]
        public int Indent { get; set; } = 10;

        [Browsable(false)]
        public TreeDataGridViewRowNodeCollection Nodes { get; } = new TreeDataGridViewRowNodeCollection();
        #endregion

        private IList dataSource { get; set; }
        public new object DataSource
        {
            get
            {
                if (TreeDataSourceNode.TreeDataSource)
                    return dataSource;
                else
                    return base.DataSource;
            }
            set
            {
                if (TreeDataSourceNode.TreeDataSource)
                {
                    if (value is DataSet ds)
                    {
                        dataSource = ((IListSource)ds.Tables[0]).GetList();
                    }
                    else if (value is IListSource listSource)
                    {
                        dataSource = listSource.GetList();
                    }
                    DataBind();
                }
                else
                    base.DataSource = value;
            }
        }
        private void DataBind()
        {
            if (dataSource == null)
                return;
            this.Nodes.Clear();
            this.Rows.Clear();
            //判定是否是数据绑定输结构模式
            DataBindTreeNode(this.Nodes, null, TreeDataSourceNode.RootContent, 0, Indent,"");
        }
        private TreeDataGridViewRowNodeCollection DataBindTreeNode(TreeDataGridViewRowNodeCollection nodes,
            DataGridViewRow parentLevel
            , string value, int level, int indent, string paternelnodePath)
        {
            IList list;
            if (dataSource is DataView rows)
            {
                rows.RowFilter = string.Format("[{0}]=\'{1}\'", TreeDataSourceNode.ParentNode, value);
                list = rows;
            }
            else
            {
                throw new NotImplementedException("请使用DataTable数据绑定");
            }
            int index = 0;
            foreach (var item in list)
            {
                int indexRow = this.Rows.Add();
                DataGridViewRow dataGridViewRow = Rows[indexRow];

                TreeDataGridViewCellValues treeData = new TreeDataGridViewCellValues();
                string nodePath = paternelnodePath + "/" + index++;
                TreeDataGridViewRowNode node = new TreeDataGridViewRowNode()
                {
                    DataGridView = this,
                    ParentLevel = parentLevel,
                    DataGridViewRow= dataGridViewRow,
                };


                string parentValue = string.Empty;
                if (item is DataRowView row)
                {
                    parentValue = row[TreeDataSourceNode.ChildNode]?.ToString();
                    foreach (DataGridViewColumn column in base.Columns)
                    {
                        DataGridViewCell cell = column.CellTemplate;

                        if (cell is WenTreeDataGridViewTextBoxCell)
                        {
                            treeData = new TreeDataGridViewCellValues()
                            {
                                Text = row[column.DataPropertyName]?.ToString(),
                                Level = level,
                                Indent = indent,
                                NodePath = nodePath,
                            };
                            dataGridViewRow.Cells[column.Name].Value = treeData;
                        }
                        else
                        {
                            dataGridViewRow.Cells[column.Name].Value = row[column.DataPropertyName];
                        }
                    }
                }

                nodes.Add(node);
                var subnodes = DataBindTreeNode(node.Nodes, dataGridViewRow, parentValue, level + 1, indent, nodePath);
                treeData.Nodes = subnodes;
                treeData.TreeDataGridViewRowNode = node;
                node.Nodes = subnodes;
            }
            return nodes;
        }

        //在抬头行增加序号
        protected override void OnRowPostPaint(DataGridViewRowPostPaintEventArgs e)
        {
            base.OnRowPostPaint(e);
            try
            {
                Graphics g = e.Graphics;
                Rectangle recLine = e.RowBounds;
                recLine.Width = this.RowHeadersWidth - 15;
                recLine.X = 15;

                //绘制行直线
                //g.DrawLine(new Pen(Brushes.Gray),
                //    e.RowBounds.X,
                //    e.RowBounds.Y - 1,
                //    e.RowBounds.X + Width,
                //    e.RowBounds.Y - 1
                //    );
                //g.DrawLine(new Pen(Brushes.Gray),
                //    e.RowBounds.X,
                //    e.RowBounds.Y - 1 + e.RowBounds.Height,
                //    e.RowBounds.X + Width,
                //    e.RowBounds.Y - 1 + e.RowBounds.Height
                //    );


                SolidBrush b = new SolidBrush(this.RowHeadersDefaultCellStyle.ForeColor);

                g.DrawString((e.RowIndex + 1).ToString(System.Globalization.CultureInfo.CurrentUICulture)
                    , this.DefaultCellStyle.Font, b, recLine, StringConters);
            }
            catch { }
        }
        protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)
        {

        }
        protected override void OnCellMouseDown(DataGridViewCellMouseEventArgs e)
        {
            base.OnCellMouseDown(e);
            if (e.RowIndex < 0 || e.ColumnIndex < 0)
                return;
            var cell = this.Rows[e.RowIndex].Cells[e.ColumnIndex];
            var row = this.Rows[e.RowIndex];
            if (cell is WenDataGridViewTextBoxButtonCell)
            {
                Rectangle cellRec = this.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, true);
                Rectangle rec = new Rectangle(cellRec.Width - 20, 0, cellRec.Width, cellRec.Height);

                if (rec.Contains(e.Location))
                {
                    OnTextBoxButtonClick(e);
                }
            }
            else if(cell is WenTreeDataGridViewTextBoxCell)
            {
                if (cell.Value is TreeDataGridViewCellValues treeData)
                {
                    Rectangle cellRec = this.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, true);
                    Rectangle rec = new Rectangle(treeData.Level * treeData.Indent
                        , (cellRec.Height - 16) / 2, 16, 16);
                    if (rec.Contains(e.Location))
                    {
                        if (!treeData.CellState)
                        {
                            CloseSubNode(treeData.Nodes, e.ColumnIndex);
                            treeData.CellState = true;
                        }
                        else
                        {
                            foreach (TreeDataGridViewRowNode item in treeData.Nodes)
                            {
                                item.DataGridViewRow.Visible = true;
                            }
                            treeData.CellState = false;
                        }
                    }
                }
            }
        }
        private void CloseSubNode(TreeDataGridViewRowNodeCollection nodes,int columnIndex)
        {
            foreach (TreeDataGridViewRowNode item in nodes)
            {
                item.DataGridViewRow.Visible = false;
                if (item.DataGridViewRow.Cells[columnIndex].Value is TreeDataGridViewCellValues values)
                {
                    values.CellState = true;
                }
                if (item.Nodes.Count > 0)
                    CloseSubNode(item.Nodes, columnIndex);
            }
        }
    }
    public class WenDataGridViewTextBoxButtonColumn : DataGridViewColumn
    {
        private static WenDataGridViewTextBoxButtonCell wencell = new WenDataGridViewTextBoxButtonCell();
        public WenDataGridViewTextBoxButtonColumn() : base(wencell)
        {
            CellTemplate = wencell;
        }
    }

    public class WenDataGridViewTextBoxButtonCell : DataGridViewTextBoxCell
    {
        public WenDataGridViewTextBoxButtonCell() : base()
        {
        }
        public int Width { get; set; }
        public int Height { get; set; }
        public bool ButtonClick { get; set; }

        protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
        {
            base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
            Width = cellBounds.Width;
            Height = cellBounds.Height;

            //计算按钮区域
            Rectangle rec = new Rectangle(cellBounds.X + (cellBounds.Width - 15), cellBounds.Y + (cellBounds.Height - 20) / 2, 13, 20);
            if (ButtonClick)
            {
                //ButtonRenderer.DrawButton(graphics, rec, "", cellStyle.Font, false, PushButtonState.Pressed);
                ButtonRenderer.DrawButton(graphics, rec, PushButtonState.Pressed);
                ButtonClick = false;
            }
            else
            {
                //ButtonRenderer.DrawButton(graphics, rec, "", cellStyle.Font, false, PushButtonState.Normal);
                ButtonRenderer.DrawButton(graphics, rec, PushButtonState.Normal);
            }
        }
        protected override void OnMouseClick(DataGridViewCellMouseEventArgs e)
        {
            base.OnMouseClick(e);
            //计算按钮区域
            Rectangle rec = new Rectangle(Width - 20, 0, Width, Height);

            if (rec.Contains(e.Location))
            {
                ButtonClick = true;
            }
        }
    }

    public class WenTreeDataGridViewTextBoxColumn: DataGridViewColumn
    {
        private static WenTreeDataGridViewTextBoxCell wencell = new WenTreeDataGridViewTextBoxCell();
        public WenTreeDataGridViewTextBoxColumn() : base(wencell)
        {
            CellTemplate = wencell;
        }
    }
    public class WenTreeDataGridViewTextBoxCell: DataGridViewTextBoxCell
    {

        protected override void Paint(Graphics g, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
        {
            base.Paint(g, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);

            if (value is TreeDataGridViewCellValues treeData)
            {
                int indent = treeData.Indent * treeData.Level + 3;

                RectangleF rec = new RectangleF(cellBounds.X, cellBounds.Y, cellBounds.Width - 1, cellBounds.Height - 1);


                ControlHelper.SetGDIHigh(g);

                RectangleF recStr = new RectangleF(rec.X + 16 + indent, rec.Y, rec.Width, rec.Height);

                if ((cellState | DataGridViewElementStates.Selected) == cellState)
                {
                    g.FillRectangle(new SolidBrush(cellStyle.SelectionBackColor), rec);
                    g.DrawString(treeData.Text, cellStyle.Font, new SolidBrush(cellStyle.SelectionForeColor), recStr, ControlHelper.StringConters);
                }
                else
                {
                    g.FillRectangle(new SolidBrush(cellStyle.BackColor), rec);
                    g.DrawString(treeData.Text, cellStyle.Font, new SolidBrush(cellStyle.ForeColor), recStr, ControlHelper.StringConters);
                }

                Image image = WenSkin.Properties.Resources.reduce;
                if (treeData.CellState)
                    image = WenSkin.Properties.Resources.add;
                
                g.DrawImage(image, rec.X + indent, rec.Y + (rec.Height - 16) / 2, 16, 16);
            }
        }
    }

    public class TreeDataGridViewCellValues
    {
        //当前级别
        public int Level { get; set; }
        //当前文本
        public string Text { get; set; }
        //节点伸缩值
        public int Indent { get; set; } = 20;

        //节点打开状态。true 打开
        public bool CellState { get; set; } = false;

        public string NodePath { get; set; }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [Category("Wen")]
        [Description("子级数据集合")]
        public TreeDataGridViewRowNodeCollection Nodes { get; set; } = new TreeDataGridViewRowNodeCollection();

        public TreeDataGridViewRowNode TreeDataGridViewRowNode { get; set; }
        public override string ToString()
        {
            return Text;
        }
    }

    public class TreeDataGridViewRowNodeCollection:IList
    {
        public ArrayList List { get; } = new ArrayList();
        public object this[int index] { get => List[index]; set => List[index] = value; }

        public bool IsReadOnly => List.IsReadOnly;

        public bool IsFixedSize => List.IsFixedSize;

        public int Count => List.Count;

        public object SyncRoot => List.SyncRoot;

        public bool IsSynchronized => List.IsSynchronized;

        public int Add(object value)
        {
            return List.Add(value);
        }
        public void AddRange<T>(IEnumerable<T> collection) where T : class
        {
            foreach (var item in collection)
            {
                List.Add(item);
            }
        }
        internal void AddRange<T>(TreeDataGridViewRowNodeCollection treeDataGridViewRowNodeCollection)
        {
            foreach (var item in treeDataGridViewRowNodeCollection)
            {
                List.Add(item);
            }
        }

        public void Clear()
        {
            List.Clear();
        }

        public bool Contains(object value)
        {
            return List.Contains(value);
        }

        public void CopyTo(Array array, int index)
        {
            List.CopyTo(array, index);
        }

        public IEnumerator GetEnumerator()
        {
            return List.GetEnumerator();
        }

        public int IndexOf(object value)
        {
            return List.IndexOf(value);
        }

        public void Insert(int index, object value)
        {
            List.Insert(index, value);
        }

        public void Remove(object value)
        {
            List.Remove(value);
        }

        public void RemoveAt(int index)
        {
            List.RemoveAt(index);
        }


    }

    public class TreeDataGridViewRowNode
    {
        public DataGridView DataGridView { get; set; }
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [Category("Wen")]
        [Description("当前单元格所在级别")]
        public int Level { get; set; }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [Category("Wen")]
        [Description("当前单元格内容")]
        public DataGridViewRow DataGridViewRow { get; set; }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [Category("Wen")]
        [Description("父级单元格内容")]
        public DataGridViewRow ParentLevel { get; set; }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [Category("Wen")]
        [Description("子级数据集合")]
        public TreeDataGridViewRowNodeCollection Nodes { get; set; } = new TreeDataGridViewRowNodeCollection();
    }
}
